﻿using System;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;


namespace DKE_Kinect.Entwicklung.Grafik.ControlManaging
{
	/// <summary>
	/// Repräsentiert eine Schaltfläche.
	/// </summary>
	public class Button : Control
	{
		#region Fields

		private int pButtonIndex;

		private bool pHoverEffectActive;

		private Texture2D pHoverTexture;

		private Texture2D pIcon;
		private float pIconAlpha;
		private Rectangle pIconBounds;

		private TextureAlphaFadeTransition pFadeHover;

		#endregion

		#region Constructors

		/// <summary>
		/// Instanziiert ein neues Objekt dieser Klasse.
		/// </summary>
		/// <param name="Name">Eindeutiger Name.</param>
		public Button (string Name)
			: this(Name, 4)
		{ }

		/// <summary>
		/// Instaziiert ein neues Objekt dieser Klasse.
		/// </summary>
		/// <param name="Name">Eindeutiger Name.</param>
		/// <param name="Type">Typ der Schaltfläche.</param>
		/// <param name="ButtonIndex">Weitere Spezifikation der Schaltläche.</param>
		public Button (string Name, ButtonType Type, int ButtonIndex)
			: base(Name)
		{
			this.pButtonIndex = ButtonIndex;

			this.pHoverEffectActive = false;
			this.pFadeHover = new TextureAlphaFadeTransition(0f, 1f, (new TimeSpan(0, 0, 0, 0, 300)).Ticks);
			this.pFadeHover.TransitionFinished += new EventHandler(this.HoverFinished);

			base.Texture = ContainerRessources.GetButtons(Type)[ButtonIndex];
			this.pHoverTexture = ContainerRessources.GetButtons(ContainerRessources.Pendant(Type))[ButtonIndex];
			this.Bounds = base.Texture.Bounds;

			this.pIcon = null;
			this.pIconAlpha = 1f;
			this.pIconBounds = new Rectangle();
		}

		/// <summary>
		/// Initializes a new instance of the <see cref="Button"/> class.
		/// </summary>
		/// <param name="Name">The name.</param>
		/// <param name="ButtonIndex">Zero based - Index of the button.</param>
		public Button (string Name, int ButtonIndex)
			: this(Name, ButtonType.MainMenuStatic, ButtonIndex)
		{ }

		#endregion

		#region Properties



		/// <summary>
		/// Gibt die Textur an, die angezeigt wird, wenn sie den Pseudo-Fokus besitzt oder legt diese fest.
		/// </summary>
		public Texture2D HoverTexture { get { return this.pHoverTexture; } set { this.pHoverTexture = value; } }

		/// <summary>
		/// Gibt ein Icon an, das auf dem Button zusätzlich gezeichnet wird oder legt dieses fest.
		/// </summary>
		public Texture2D Icon { get { return this.pIcon; } set { this.pIcon = value; } }
		/// <summary>
		/// Gibt die Durchsichtigkeit des Icons an oder legt diese fest.
		/// </summary>
		public float IconAlpha
		{
			get { return this.pAlpha; }
			set
			{
				if ((value < 0f) || (value > 1f))
					throw new System.ArgumentOutOfRangeException();

				this.pIconAlpha = value;
			}
		}
		/// <summary>
		/// Gibt die Grenzen für das Icon an oder legt diese fest. Nur wenn keine Kante des Rechtecks die Grenzen der Schaltfläche überschreitet, wird das Icon gezeichnet.
		/// </summary>
		public Rectangle IconBounds { get { return this.pIconBounds; } set { this.pIconBounds = value; } }

		#endregion

		#region Methods

		/// <summary>
		/// Führt ein Update für diese und alle untergeordneten Komponenten aus.
		/// </summary>
		/// <param name="gameTime"></param>
		public override void Update (GameTime gameTime)
		{
			base.Update(gameTime);

			this.pFadeHover.Update(gameTime.ElapsedGameTime.Ticks);
		}

		/// <summary>
		/// Löst das Paint - Ereignis aus.
		/// </summary>
		/// <param name="e"></param>
		protected override void OnPaint (PaintEventArgs e)
		{
			if (this.pFadeHover.Working || this.pHoverEffectActive)
			{
				if (!this.pTextureBounds.HasValue || !this.pVisibleScreenBounds.HasValue)
					return;

				this.pFadeHover.Draw(
					e.Sprite,
					this.pTexture, this.pHoverTexture,
					this.pTeint * this.pBufferedAlpha.GetValueOrDefault(this.pAlpha),
					this.pVisibleScreenBounds.Value, this.pTextureBounds, new Vector2(0, 0));
			}
			else if (!this.pMouseHovers)
			{
				base.OnPaint(e);
			}

			if (this.pIcon != null)
			{
				if (!this.pVisibleScreenBounds.HasValue)
					return;

				if ((this.pIconBounds.Left >= this.pBounds.Right) || (this.pIconBounds.Right < 0) || (this.pIconBounds.Top >= this.pBounds.Bottom) || (this.pIconBounds.Bottom < 0))
					return;

				Rectangle drawRect = new Rectangle(
					this.pRelativeScreenBounds.Value.Left + this.pIconBounds.Left,
					this.pRelativeScreenBounds.Value.Top + this.pIconBounds.Top,
					this.pIconBounds.Width, this.pIconBounds.Height);

				e.Sprite.Draw(this.pIcon, drawRect, Color.White * this.pIconAlpha * this.pBufferedAlpha.GetValueOrDefault(this.pAlpha));
			}
		}

		/// <summary>
		/// Wechselt den "Aktiviert - Effekt" in die entgegengesetzte Richtung (sobald Maus darüber fährt oder Pseudo - Fokus erhält).
		/// </summary>
		public void ChangeHoverEffect ()
		{
			if (this.pFadeHover.Working)
				this.pFadeHover.Revert();
			else
			{
				if (!this.pFadeHover.Finished && this.pFadeHover.Idle)
					this.ActivateHoverEffect();
				else
				{
					if (this.pFadeHover.Reverted)
						this.ActivateHoverEffect();
					else
						this.DeactivateHoverEffect();
				}
			}
		}

		/// <summary>
		/// Aktiviert den "Aktiviert - Effekt" (sobald Maus darüber fährt oder Pseudo - Fokus erhält).
		/// </summary>
		public void ActivateHoverEffect ()
		{
			if (!this.pVisible)
				this.DeactivateHoverEffect();
			else
			{
				if (this.pFadeHover.Idle)
					this.pFadeHover.BeginFromFront();

				this.pHoverEffectActive = true;
			}
		}
		/// <summary>
		/// Deaktiviert den "Aktiviert - Effekt" (sobald Maus darüber fährt oder Pseudo - Fokus erhält).
		/// </summary>
		public void DeactivateHoverEffect ()
		{
			if (!this.pVisible)
			{
				this.pFadeHover.BeginFromFront();
				this.pFadeHover.Reset();
				this.pHoverEffectActive = false;
			}
			else
			{
				if (this.pFadeHover.Idle)
					this.pFadeHover.BeginFromBack();

				this.pHoverEffectActive = true;
			}
		}

		// Events
		private void HoverFinished (object sender, EventArgs e)
		{
			if (this.pFadeHover.Reverted)
				this.pHoverEffectActive = false;
		}

		// Event Handling Overrides
		/// <summary>
		/// Löst das Ergebnis VisisbleChanged aus.
		/// </summary>
		/// <param name="e"></param>
		protected override void OnVisibleChanged (EventArgs e)
		{
			if (!this.pVisible)
				this.DeactivateHoverEffect();

			this.pHoverEffectActive = false;
			base.OnVisibleChanged(e);
		}

		/// <summary>
		/// Löst das Ereignis MouseEnter aus.
		/// </summary>
		/// <param name="e"></param>
		protected override void OnMouseEnter (EventArgs e)
		{
			if (this.pEnabled)
			{
				if (this.pFadeHover.Idle)
					this.pFadeHover.BeginFromFront();
				else
					this.pFadeHover.Revert();

				base.OnMouseEnter(e);
			}
		}
		/// <summary>
		/// Löst das Ereignis MouseLeave aus.
		/// </summary>
		/// <param name="e"></param>
		protected override void OnMouseLeave (EventArgs e)
		{
			if (this.pEnabled)
			{
				if (this.pFadeHover.Idle)
					this.pFadeHover.BeginFromBack();
				else
					this.pFadeHover.Revert();

				base.OnMouseLeave(e);
			}
		}

		#endregion
	}
}
